
#include "snake.h"
#include <QRandomGenerator>
#include <QDebug>
//#include <QPainter>




Snake::Snake(int x, int y, QObject *parent)
 : QObject{parent}
{
    locx = x;
    locy = y;

    snakeBlockWidth = 23;
    snakeBlockHeight = 23;

    //位置变换速度
    movelocx = 0;
    movelocy = 0;

    //初始化为一个蛇长
    this->snakebody.append(QRectF(0, 0, this->snakeBlockWidth, this->snakeBlockHeight));

    //初始化一个方向
    this->movedirect = (enum Direct)QRandomGenerator::global()->bounded(0, 4);

    //初始化刷新速度
    activetime = 100;

    //初始化速度比率
    this->movespeed = 5;

    connect(this, &Snake::fail, this, &Snake::stop);
    connect(&timer, &QTimer::timeout, this, &Snake::allupdate);

}

void Snake::setloc(int x, int y)
{
    locx = x;
    locy = y;
    //qDebug()<<x<<y;
}

void Snake::updatebodysize(int newwidth, int newheight)
{
    this->snakeBlockWidth = newwidth;
    this->snakeBlockHeight = newheight;
    for (int i=0; i<this->snakebody.length(); ++i)
    {
        this->snakebody[i].setWidth(this->snakeBlockWidth);
        this->snakebody[i].setHeight(this->snakeBlockHeight);
    }

}

void Snake::allupdate()
{
    //qDebug()<<"ef";
    move();
    emit check();
    longer(ISADD);
    ISADD = 0;
    checkfail();
}

void Snake::checkfail()
{
    for (int i=snakebody.size()-1; i>=4; --i)
    {
        if (snakebody[i]==snakebody[0]) {
            emit(fail());
        }
    }
    qreal reallocx = this->snakebody[0].x()+locx;
    qreal reallocy = this->snakebody[0].y()+locy;
    if (reallocx>rightmax||reallocx<0) emit(fail());
    if (reallocy>buttommax||reallocy<0) emit(fail());
}

void Snake::paintsnake(QPainter & painter)
{
//    qreal devicew = painter.device()->width();
//    qreal deviceh = painter.device()->height();
//    qDebug()<<devicew<<deviceh<<this->movedirect;
    painter.save();
    painter.translate(locx, locy);
    painter.drawRects(snakebody);
    painter.restore();
}

//以屏幕的左上角为原点即(0, 0)点，从左向右为x轴正向，从上向下为y轴正向.

void Snake::move()
{
    int headx = snakebody[0].x() + gox[movedirect] * snakeBlockWidth;
    int heady = snakebody[0].y() + goy[movedirect] * snakeBlockHeight;
    this->snakebody.insert(0, QRectF(headx, heady, snakeBlockWidth, snakeBlockHeight));

    locx = locx + gox[movedirect] * movelocx;
    locy = locy + goy[movedirect] * movelocy;

    //longer();
}

void Snake::longer(bool pd)
{
    if (pd == 0)
    {
        snakebody.removeLast();
    }
}

bool Snake::checkheadcrash(QRectF* rec)
{
    //qDebug()<<"here1";
    QRectF relrec(rec->x()-locx, rec->y()-locy, rec->width(),rec->height());

    return snakebody.at(0).intersects(relrec);
}

Snake :: RETDIRECT Snake::dir()
{
    return movedirect;
}

bool Snake::setdirect(Snake::RETDIRECT d) {
    if (d == Snake::Left && this->movedirect == Snake::Right)
    {
        return false;
    }

    if (d == Snake::Right && this->movedirect == Snake::Left)
    {
        return false;
    }

    if (d == Snake::Down && this->movedirect == Snake::Up)
    {
        return false;
    }

    if (d == Snake::Up && this->movedirect == Snake::Down)
    {
        return false;
    }

    this->movedirect = d;
    return 1;
}

void Snake::start(int sp)//开始行动
{
    setmovespeed(sp);
    this->start();
}

void Snake::start()
{
    this->timer.start(activetime * 15 / movespeed);
    //qDebug()<<"here2";
}
void Snake ::stop()
{
    this->timer.stop();
}

void Snake::changedirect(QKeyEvent *ev)
{
    switch(ev->key()){
    case Qt::Key_Up:
        setdirect(Snake::Up);
        break;
    case Qt::Key_Down:
        setdirect(Snake::Down);
        break;
    case Qt::Key_Right:
        setdirect(Snake::Right);
        break;
    case Qt::Key_Left:
        setdirect(Snake::Left);
        break;

    default:
        break;
    }
}

void Snake::setactivetime(int t)
{
    this->activetime = t;
}

void Snake::setmovespeed(int sp)
{
    this->movespeed = sp;
}

QRectF Snake::realrect(int ind)
{
    QRectF ret = snakebody[ind];
    ret.adjust(locx, locy, 0, 0);
    return ret;
}

void Snake::addblock(Block *blk)
{

    //qDebug()<<(blk->x());
    connect(this, &Snake::check, this, [=](){
        //qDebug()<<blk;
        if (checkheadcrash(blk))
        {
            ISADD = 1;
            blk->change();
        }

    });
}

void Snake::addboudary(int w, int h)
{
    this->rightmax = w;
    this->buttommax = h;
}

